home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / lib / iceweasel / components / fuelApplication.js < prev    next >
Encoding:
JavaScript  |  2013-01-09  |  37.9 KB  |  1,407 lines

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3.  *
  4.  * The contents of this file are subject to the Mozilla Public License Version
  5.  * 1.1 (the "License"); you may not use this file except in compliance with
  6.  * the License. You may obtain a copy of the License at
  7.  * http://www.mozilla.org/MPL/
  8.  *
  9.  * Software distributed under the License is distributed on an "AS IS" basis,
  10.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11.  * for the specific language governing rights and limitations under the
  12.  * License.
  13.  *
  14.  * The Original Code is FUEL.
  15.  *
  16.  * The Initial Developer of the Original Code is Mozilla Foundation.
  17.  * Portions created by the Initial Developer are Copyright (C) 2006
  18.  * the Initial Developer. All Rights Reserved.
  19.  *
  20.  * Contributor(s):
  21.  *  Mark Finkle <mfinkle@mozilla.com> (Original Author)
  22.  *  John Resig  <jresig@mozilla.com> (Original Author)
  23.  *
  24.  * Alternatively, the contents of this file may be used under the terms of
  25.  * either the GNU General Public License Version 2 or later (the "GPL"), or
  26.  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  27.  * in which case the provisions of the GPL or the LGPL are applicable instead
  28.  * of those above. If you wish to allow use of your version of this file only
  29.  * under the terms of either the GPL or the LGPL, and not to allow others to
  30.  * use your version of this file under the terms of the MPL, indicate your
  31.  * decision by deleting the provisions above and replace them with the notice
  32.  * and other provisions required by the GPL or the LGPL. If you do not delete
  33.  * the provisions above, a recipient may use your version of this file under
  34.  * the terms of any one of the MPL, the GPL or the LGPL.
  35.  *
  36.  * ***** END LICENSE BLOCK ***** */
  37.  
  38. const Ci = Components.interfaces;
  39. const Cc = Components.classes;
  40.  
  41. Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
  42.  
  43. const APPLICATION_CID = Components.ID("fe74cf80-aa2d-11db-abbd-0800200c9a66");
  44. const APPLICATION_CONTRACTID = "@mozilla.org/fuel/application;1";
  45.  
  46. //=================================================
  47. // Singleton that holds services and utilities
  48. var Utilities = {
  49.   get bookmarks() {
  50.     let bookmarks = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
  51.                     getService(Ci.nsINavBookmarksService);
  52.     this.__defineGetter__("bookmarks", function() bookmarks);
  53.     return this.bookmarks;
  54.   },
  55.  
  56.   get livemarks() {
  57.     let livemarks = Cc["@mozilla.org/browser/livemark-service;2"].
  58.                     getService(Ci.nsILivemarkService);
  59.     this.__defineGetter__("livemarks", function() livemarks);
  60.     return this.livemarks;
  61.   },
  62.  
  63.   get annotations() {
  64.     let annotations = Cc["@mozilla.org/browser/annotation-service;1"].
  65.                       getService(Ci.nsIAnnotationService);
  66.     this.__defineGetter__("annotations", function() annotations);
  67.     return this.annotations;
  68.   },
  69.  
  70.   get history() {
  71.     let history = Cc["@mozilla.org/browser/nav-history-service;1"].
  72.                   getService(Ci.nsINavHistoryService);
  73.     this.__defineGetter__("history", function() history);
  74.     return this.history;
  75.   },
  76.  
  77.   get windowMediator() {
  78.     let windowMediator = Cc["@mozilla.org/appshell/window-mediator;1"].
  79.                          getService(Ci.nsIWindowMediator);
  80.     this.__defineGetter__("windowMediator", function() windowMediator);
  81.     return this.windowMediator;
  82.   },
  83.  
  84.   makeURI : function(aSpec) {
  85.     if (!aSpec)
  86.       return null;
  87.     var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
  88.     return ios.newURI(aSpec, null, null);
  89.   },
  90.  
  91.   free : function() {
  92.     delete this.bookmarks;
  93.     delete this.livemarks
  94.     delete this.annotations;
  95.     delete this.history;
  96.     delete this.windowMediator;
  97.   }
  98. };
  99.  
  100.  
  101. //=================================================
  102. // Window implementation
  103. function Window(aWindow) {
  104.   this._window = aWindow;
  105.   this._tabbrowser = aWindow.getBrowser();
  106.   this._events = new Events();
  107.   this._cleanup = {};
  108.  
  109.   this._watch("TabOpen");
  110.   this._watch("TabMove");
  111.   this._watch("TabClose");
  112.   this._watch("TabSelect");
  113.  
  114.   var self = this;
  115.   gShutdown.push(function() { self._shutdown(); });
  116. }
  117.  
  118. Window.prototype = {
  119.   get events() {
  120.     return this._events;
  121.   },
  122.  
  123.   /*
  124.    * Helper used to setup event handlers on the XBL element. Note that the events
  125.    * are actually dispatched to tabs, so we capture them.
  126.    */
  127.   _watch : function win_watch(aType) {
  128.     var self = this;
  129.     this._tabbrowser.tabContainer.addEventListener(aType,
  130.       this._cleanup[aType] = function(e){ self._event(e); },
  131.       true);
  132.   },
  133.  
  134.   /*
  135.    * Helper event callback used to redirect events made on the XBL element
  136.    */
  137.   _event : function win_event(aEvent) {
  138.     this._events.dispatch(aEvent.type, new BrowserTab(this, aEvent.originalTarget.linkedBrowser));
  139.   },
  140.   get tabs() {
  141.     var tabs = [];
  142.     var browsers = this._tabbrowser.browsers;
  143.     for (var i=0; i<browsers.length; i++)
  144.       tabs.push(new BrowserTab(this, browsers[i]));
  145.     return tabs;
  146.   },
  147.   get activeTab() {
  148.     return new BrowserTab(this, this._tabbrowser.selectedBrowser);
  149.   },
  150.   open : function win_open(aURI) {
  151.     return new BrowserTab(this, this._tabbrowser.addTab(aURI.spec).linkedBrowser);
  152.   },
  153.   _shutdown : function win_shutdown() {
  154.     for (var type in this._cleanup)
  155.       this._tabbrowser.removeEventListener(type, this._cleanup[type], true);
  156.     this._cleanup = null;
  157.  
  158.     this._window = null;
  159.     this._tabbrowser = null;
  160.     this._events = null;
  161.   },
  162.  
  163.   QueryInterface : XPCOMUtils.generateQI([Ci.fuelIWindow])
  164. };
  165.  
  166. //=================================================
  167. // BrowserTab implementation
  168. function BrowserTab(aFUELWindow, aBrowser) {
  169.   this._window = aFUELWindow;
  170.   this._tabbrowser = aFUELWindow._tabbrowser;
  171.   this._browser = aBrowser;
  172.   this._events = new Events();
  173.   this._cleanup = {};
  174.  
  175.   this._watch("load");
  176.  
  177.   var self = this;
  178.   gShutdown.push(function() { self._shutdown(); });
  179. }
  180.  
  181. BrowserTab.prototype = {
  182.   get uri() {
  183.     return this._browser.currentURI;
  184.   },
  185.  
  186.   get index() {
  187.     var tabs = this._tabbrowser.tabs;
  188.     for (var i=0; i<tabs.length; i++) {
  189.       if (tabs[i].linkedBrowser == this._browser)
  190.         return i;
  191.     }
  192.     return -1;
  193.   },
  194.  
  195.   get events() {
  196.     return this._events;
  197.   },
  198.  
  199.   get window() {
  200.     return this._window;
  201.   },
  202.  
  203.   get document() {
  204.     return this._browser.contentDocument;
  205.   },
  206.  
  207.   /*
  208.    * Helper used to setup event handlers on the XBL element
  209.    */
  210.   _watch : function bt_watch(aType) {
  211.     var self = this;
  212.     this._browser.addEventListener(aType,
  213.       this._cleanup[aType] = function(e){ self._event(e); },
  214.       true);
  215.   },
  216.  
  217.   /*
  218.    * Helper event callback used to redirect events made on the XBL element
  219.    */
  220.   _event : function bt_event(aEvent) {
  221.     if (aEvent.type == "load") {
  222.       if (!(aEvent.originalTarget instanceof Ci.nsIDOMDocument))
  223.         return;
  224.  
  225.       if (aEvent.originalTarget.defaultView instanceof Ci.nsIDOMWindow &&
  226.           aEvent.originalTarget.defaultView.frameElement)
  227.         return;
  228.     }
  229.     this._events.dispatch(aEvent.type, this);
  230.   },
  231.   /*
  232.    * Helper used to determine the index offset of the browsertab
  233.    */
  234.   _getTab : function bt_gettab() {
  235.     var tabs = this._tabbrowser.tabs;
  236.     return tabs[this.index] || null;
  237.   },
  238.  
  239.   load : function bt_load(aURI) {
  240.     this._browser.loadURI(aURI.spec, null, null);
  241.   },
  242.  
  243.   focus : function bt_focus() {
  244.     this._tabbrowser.selectedTab = this._getTab();
  245.     this._tabbrowser.focus();
  246.   },
  247.  
  248.   close : function bt_close() {
  249.     this._tabbrowser.removeTab(this._getTab());
  250.   },
  251.  
  252.   moveBefore : function bt_movebefore(aBefore) {
  253.     this._tabbrowser.moveTabTo(this._getTab(), aBefore.index);
  254.   },
  255.  
  256.   moveToEnd : function bt_moveend() {
  257.     this._tabbrowser.moveTabTo(this._getTab(), this._tabbrowser.browsers.length);
  258.   },
  259.  
  260.   _shutdown : function bt_shutdown() {
  261.     for (var type in this._cleanup)
  262.       this._browser.removeEventListener(type, this._cleanup[type], true);
  263.     this._cleanup = null;
  264.  
  265.     this._window = null;
  266.     this._tabbrowser = null;
  267.     this._browser = null;
  268.     this._events = null;
  269.   },
  270.  
  271.   QueryInterface : XPCOMUtils.generateQI([Ci.fuelIBrowserTab])
  272. };
  273.  
  274.  
  275. //=================================================
  276. // Annotations implementation
  277. function Annotations(aId) {
  278.   this._id = aId;
  279. }
  280.  
  281. Annotations.prototype = {
  282.   get names() {
  283.     return Utilities.annotations.getItemAnnotationNames(this._id);
  284.   },
  285.  
  286.   has : function ann_has(aName) {
  287.     return Utilities.annotations.itemHasAnnotation(this._id, aName);
  288.   },
  289.  
  290.   get : function(aName) {
  291.     if (this.has(aName))
  292.       return Utilities.annotations.getItemAnnotation(this._id, aName);
  293.     return null;
  294.   },
  295.  
  296.   set : function(aName, aValue, aExpiration) {
  297.     Utilities.annotations.setItemAnnotation(this._id, aName, aValue, 0, aExpiration);
  298.   },
  299.  
  300.   remove : function ann_remove(aName) {
  301.     if (aName)
  302.       Utilities.annotations.removeItemAnnotation(this._id, aName);
  303.   },
  304.  
  305.   QueryInterface : XPCOMUtils.generateQI([Ci.fuelIAnnotations])
  306. };
  307.  
  308.  
  309. //=================================================
  310. // Bookmark implementation
  311. function Bookmark(aId, aParent, aType) {
  312.   this._id = aId;
  313.   this._parent = aParent;
  314.   this._type = aType || "bookmark";
  315.   this._annotations = new Annotations(this._id);
  316.   this._events = new Events();
  317.  
  318.   Utilities.bookmarks.addObserver(this, false);
  319.  
  320.   var self = this;
  321.   gShutdown.push(function() { self._shutdown(); });
  322. }
  323.  
  324. Bookmark.prototype = {
  325.   _shutdown : function bm_shutdown() {
  326.     this._annotations = null;
  327.     this._events = null;
  328.  
  329.     Utilities.bookmarks.removeObserver(this);
  330.   },
  331.  
  332.   get id() {
  333.     return this._id;
  334.   },
  335.  
  336.   get title() {
  337.     return Utilities.bookmarks.getItemTitle(this._id);
  338.   },
  339.  
  340.   set title(aTitle) {
  341.     Utilities.bookmarks.setItemTitle(this._id, aTitle);
  342.   },
  343.  
  344.   get uri() {
  345.     return Utilities.bookmarks.getBookmarkURI(this._id);
  346.   },
  347.  
  348.   set uri(aURI) {
  349.     return Utilities.bookmarks.changeBookmarkURI(this._id, aURI);
  350.   },
  351.  
  352.   get description() {
  353.     return this._annotations.get("bookmarkProperties/description");
  354.   },
  355.  
  356.   set description(aDesc) {
  357.     this._annotations.set("bookmarkProperties/description", aDesc, Ci.nsIAnnotationService.EXPIRE_NEVER);
  358.   },
  359.  
  360.   get keyword() {
  361.     return Utilities.bookmarks.getKeywordForBookmark(this._id);
  362.   },
  363.  
  364.   set keyword(aKeyword) {
  365.     Utilities.bookmarks.setKeywordForBookmark(this._id, aKeyword);
  366.   },
  367.  
  368.   get type() {
  369.     return this._type;
  370.   },
  371.  
  372.   get parent() {
  373.     return this._parent;
  374.   },
  375.  
  376.   set parent(aFolder) {
  377.     Utilities.bookmarks.moveItem(this._id, aFolder.id, Utilities.bookmarks.DEFAULT_INDEX);
  378.     // this._parent is updated in onItemMoved
  379.   },
  380.  
  381.   get annotations() {
  382.     return this._annotations;
  383.   },
  384.  
  385.   get events() {
  386.     return this._events;
  387.   },
  388.  
  389.   remove : function bm_remove() {
  390.     Utilities.bookmarks.removeItem(this._id);
  391.   },
  392.  
  393.   // observer
  394.   onBeginUpdateBatch : function bm_obub() {
  395.   },
  396.  
  397.   onEndUpdateBatch : function bm_oeub() {
  398.   },
  399.  
  400.   onItemAdded : function bm_oia(aId, aFolder, aIndex, aItemType, aURI) {
  401.     // bookmark object doesn't exist at this point
  402.   },
  403.  
  404.   onBeforeItemRemoved : function bm_obir(aId) {
  405.   },
  406.  
  407.   onItemRemoved : function bm_oir(aId, aFolder, aIndex) {
  408.     if (this._id == aId)
  409.       this._events.dispatch("remove", aId);
  410.   },
  411.  
  412.   onItemChanged : function bm_oic(aId, aProperty, aIsAnnotationProperty, aValue) {
  413.     if (this._id == aId)
  414.       this._events.dispatch("change", aProperty);
  415.   },
  416.  
  417.   onItemVisited: function bm_oiv(aId, aVisitID, aTime) {
  418.   },
  419.  
  420.   onItemMoved: function bm_oim(aId, aOldParent, aOldIndex, aNewParent, aNewIndex) {
  421.     if (this._id == aId) {
  422.       this._parent = new BookmarkFolder(aNewParent, Utilities.bookmarks.getFolderIdForItem(aNewParent));
  423.       this._events.dispatch("move", aId);
  424.     }
  425.   },
  426.  
  427.   QueryInterface : XPCOMUtils.generateQI([Ci.fuelIBookmark, Ci.nsINavBookmarkObserver])
  428. };
  429.  
  430.  
  431. //=================================================
  432. // BookmarkFolder implementation
  433. function BookmarkFolder(aId, aParent) {
  434.   this._id = aId;
  435.   this._parent = aParent;
  436.   this._annotations = new Annotations(this._id);
  437.   this._events = new Events();
  438.  
  439.   Utilities.bookmarks.addObserver(this, false);
  440.  
  441.   var self = this;
  442.   gShutdown.push(function() { self._shutdown(); });
  443. }
  444.  
  445. BookmarkFolder.prototype = {
  446.   _shutdown : function bmf_shutdown() {
  447.     this._annotations = null;
  448.     this._events = null;
  449.  
  450.     Utilities.bookmarks.removeObserver(this);
  451.   },
  452.  
  453.   get id() {
  454.     return this._id;
  455.   },
  456.  
  457.   get title() {
  458.     return Utilities.bookmarks.getItemTitle(this._id);
  459.   },
  460.  
  461.   set title(aTitle) {
  462.     Utilities.bookmarks.setItemTitle(this._id, aTitle);
  463.   },
  464.  
  465.   get description() {
  466.     return this._annotations.get("bookmarkProperties/description");
  467.   },
  468.  
  469.   set description(aDesc) {
  470.     this._annotations.set("bookmarkProperties/description", aDesc, Ci.nsIAnnotationService.EXPIRE_NEVER);
  471.   },
  472.  
  473.   get type() {
  474.     return "folder";
  475.   },
  476.  
  477.   get parent() {
  478.     return this._parent;
  479.   },
  480.  
  481.   set parent(aFolder) {
  482.     Utilities.bookmarks.moveItem(this._id, aFolder.id, Utilities.bookmarks.DEFAULT_INDEX);
  483.     // this._parent is updated in onItemMoved
  484.   },
  485.  
  486.   get annotations() {
  487.     return this._annotations;
  488.   },
  489.  
  490.   get events() {
  491.     return this._events;
  492.   },
  493.  
  494.   get children() {
  495.     var items = [];
  496.  
  497.     var options = Utilities.history.getNewQueryOptions();
  498.     var query = Utilities.history.getNewQuery();
  499.     query.setFolders([this._id], 1);
  500.     var result = Utilities.history.executeQuery(query, options);
  501.     var rootNode = result.root;
  502.     rootNode.containerOpen = true;
  503.     var cc = rootNode.childCount;
  504.     for (var i=0; i<cc; ++i) {
  505.       var node = rootNode.getChild(i);
  506.       if (node.type == node.RESULT_TYPE_FOLDER) {
  507.         var folder = new BookmarkFolder(node.itemId, this._id);
  508.         items.push(folder);
  509.       }
  510.       else if (node.type == node.RESULT_TYPE_SEPARATOR) {
  511.         var separator = new Bookmark(node.itemId, this._id, "separator");
  512.         items.push(separator);
  513.       }
  514.       else {
  515.         var bookmark = new Bookmark(node.itemId, this._id, "bookmark");
  516.         items.push(bookmark);
  517.       }
  518.     }
  519.     rootNode.containerOpen = false;
  520.  
  521.     return items;
  522.   },
  523.  
  524.   addBookmark : function bmf_addbm(aTitle, aUri) {
  525.     var newBookmarkID = Utilities.bookmarks.insertBookmark(this._id, aUri, Utilities.bookmarks.DEFAULT_INDEX, aTitle);
  526.     var newBookmark = new Bookmark(newBookmarkID, this, "bookmark");
  527.     return newBookmark;
  528.   },
  529.  
  530.   addSeparator : function bmf_addsep() {
  531.     var newBookmarkID = Utilities.bookmarks.insertSeparator(this._id, Utilities.bookmarks.DEFAULT_INDEX);
  532.     var newBookmark = new Bookmark(newBookmarkID, this, "separator");
  533.     return newBookmark;
  534.   },
  535.  
  536.   addFolder : function bmf_addfolder(aTitle) {
  537.     var newFolderID = Utilities.bookmarks.createFolder(this._id, aTitle, Utilities.bookmarks.DEFAULT_INDEX);
  538.     var newFolder = new BookmarkFolder(newFolderID, this);
  539.     return newFolder;
  540.   },
  541.  
  542.   remove : function bmf_remove() {
  543.     Utilities.bookmarks.removeItem(this._id);
  544.   },
  545.  
  546.   // observer
  547.   onBeginUpdateBatch : function bmf_obub() {
  548.   },
  549.  
  550.   onEndUpdateBatch : function bmf_oeub() {
  551.   },
  552.  
  553.   onItemAdded : function bmf_oia(aId, aFolder, aIndex, aItemType, aURI) {
  554.     // handle root folder events
  555.     if (!this._parent)
  556.       this._events.dispatch("add", aId);
  557.  
  558.     // handle this folder events
  559.     if (this._id == aFolder)
  560.       this._events.dispatch("addchild", aId);
  561.   },
  562.  
  563.   onBeforeItemRemoved : function bmf_oir(aId) {
  564.   },
  565.  
  566.   onItemRemoved : function bmf_oir(aId, aFolder, aIndex) {
  567.     // handle root folder events
  568.     if (!this._parent || this._id == aId)
  569.       this._events.dispatch("remove", aId);
  570.  
  571.     // handle this folder events
  572.     if (this._id == aFolder)
  573.       this._events.dispatch("removechild", aId);
  574.   },
  575.  
  576.   onItemChanged : function bmf_oic(aId, aProperty, aIsAnnotationProperty, aValue) {
  577.     // handle root folder and this folder events
  578.     if (!this._parent || this._id == aId)
  579.       this._events.dispatch("change", aProperty);
  580.   },
  581.  
  582.   onItemVisited: function bmf_oiv(aId, aVisitID, aTime) {
  583.   },
  584.  
  585.   onItemMoved: function bmf_oim(aId, aOldParent, aOldIndex, aNewParent, aNewIndex) {
  586.     // handle this folder event, root folder cannot be moved
  587.     if (this._id == aId) {
  588.       this._parent = new BookmarkFolder(aNewParent, Utilities.bookmarks.getFolderIdForItem(aNewParent));
  589.       this._events.dispatch("move", aId);
  590.     }
  591.   },
  592.  
  593.   QueryInterface : XPCOMUtils.generateQI([Ci.fuelIBookmarkFolder, Ci.nsINavBookmarkObserver])
  594. };
  595.  
  596. //=================================================
  597. // BookmarkRoots implementation
  598. function BookmarkRoots() {
  599.   var self = this;
  600.   gShutdown.push(function() { self._shutdown(); });
  601. }
  602.  
  603. BookmarkRoots.prototype = {
  604.   _shutdown : function bmr_shutdown() {
  605.     this._menu = null;
  606.     this._toolbar = null;
  607.     this._tags = null;
  608.     this._unfiled = null;
  609.   },
  610.  
  611.   get menu() {
  612.     if (!this._menu)
  613.       this._menu = new BookmarkFolder(Utilities.bookmarks.bookmarksMenuFolder, null);
  614.  
  615.     return this._menu;
  616.   },
  617.  
  618.   get toolbar() {
  619.     if (!this._toolbar)
  620.       this._toolbar = new BookmarkFolder(Utilities.bookmarks.toolbarFolder, null);
  621.  
  622.     return this._toolbar;
  623.   },
  624.  
  625.   get tags() {
  626.     if (!this._tags)
  627.       this._tags = new BookmarkFolder(Utilities.bookmarks.tagsFolder, null);
  628.  
  629.     return this._tags;
  630.   },
  631.  
  632.   get unfiled() {
  633.     if (!this._unfiled)
  634.       this._unfiled = new BookmarkFolder(Utilities.bookmarks.unfiledBookmarksFolder, null);
  635.  
  636.     return this._unfiled;
  637.   },
  638.  
  639.   QueryInterface : XPCOMUtils.generateQI([Ci.fuelIBookmarkRoots])
  640. };
  641.  
  642.  
  643. //=================================================
  644. // Factory - Treat Application as a singleton
  645. // XXX This is required, because we're registered for the 'JavaScript global
  646. // privileged property' category, whose handler always calls createInstance.
  647. // See bug 386535.
  648. var gSingleton = null;
  649. var ApplicationFactory = {
  650.   createInstance: function af_ci(aOuter, aIID) {
  651.     if (aOuter != null)
  652.       throw Components.results.NS_ERROR_NO_AGGREGATION;
  653.  
  654.     if (gSingleton == null) {
  655.       gSingleton = new Application();
  656.     }
  657.  
  658.     return gSingleton.QueryInterface(aIID);
  659.   }
  660. };
  661.  
  662.  
  663. //=================================================
  664. // Application constructor
  665. function Application() {
  666.   this.initToolkitHelpers();
  667.   this._bookmarks = null;
  668. }
  669.  
  670. //=================================================
  671. // Application implementation
  672. Application.prototype = {
  673.   // for nsIClassInfo + XPCOMUtils
  674.   classID:          APPLICATION_CID,
  675.  
  676.   // redefine the default factory for XPCOMUtils
  677.   _xpcom_factory: ApplicationFactory,
  678.  
  679.   // for nsISupports
  680.   QueryInterface : XPCOMUtils.generateQI([Ci.fuelIApplication, Ci.extIApplication,
  681.                                           Ci.nsIObserver]),
  682.  
  683.   // for nsIClassInfo
  684.   classInfo: XPCOMUtils.generateCI({classID: APPLICATION_CID,
  685.                                     contractID: APPLICATION_CONTRACTID,
  686.                                     interfaces: [Ci.fuelIApplication,
  687.                                                  Ci.extIApplication,
  688.                                                  Ci.nsIObserver],
  689.                                     flags: Ci.nsIClassInfo.SINGLETON}),
  690.  
  691.   // for nsIObserver
  692.   observe: function app_observe(aSubject, aTopic, aData) {
  693.     // Call the extApplication version of this function first
  694.     this.__proto__.__proto__.observe.call(this, aSubject, aTopic, aData);
  695.     if (aTopic == "xpcom-shutdown") {
  696.       this._obs.removeObserver(this, "xpcom-shutdown");
  697.       this._bookmarks = null;
  698.       Utilities.free();
  699.     }
  700.   },
  701.  
  702.   get bookmarks() {
  703.     let bookmarks = new BookmarkRoots();
  704.     this.__defineGetter__("bookmarks", function() bookmarks);
  705.     return this.bookmarks;
  706.   },
  707.  
  708.   get windows() {
  709.     var win = [];
  710.     var browserEnum = Utilities.windowMediator.getEnumerator("navigator:browser");
  711.  
  712.     while (browserEnum.hasMoreElements())
  713.       win.push(new Window(browserEnum.getNext()));
  714.  
  715.     return win;
  716.   },
  717.  
  718.   get activeWindow() {
  719.     return new Window(Utilities.windowMediator.getMostRecentWindow("navigator:browser"));
  720.   }
  721. };
  722.  
  723. /* ***** BEGIN LICENSE BLOCK *****
  724.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  725.  *
  726.  * The contents of this file are subject to the Mozilla Public License Version
  727.  * 1.1 (the "License"); you may not use this file except in compliance with
  728.  * the License. You may obtain a copy of the License at
  729.  * http://www.mozilla.org/MPL/
  730.  *
  731.  * Software distributed under the License is distributed on an "AS IS" basis,
  732.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  733.  * for the specific language governing rights and limitations under the
  734.  * License.
  735.  *
  736.  * The Original Code is FUEL.
  737.  *
  738.  * The Initial Developer of the Original Code is Mozilla Foundation.
  739.  * Portions created by the Initial Developer are Copyright (C) 2006
  740.  * the Initial Developer. All Rights Reserved.
  741.  *
  742.  * Contributor(s):
  743.  *  Mark Finkle <mfinkle@mozilla.com> (Original Author)
  744.  *  John Resig  <jresig@mozilla.com> (Original Author)
  745.  *
  746.  * Alternatively, the contents of this file may be used under the terms of
  747.  * either the GNU General Public License Version 2 or later (the "GPL"), or
  748.  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  749.  * in which case the provisions of the GPL or the LGPL are applicable instead
  750.  * of those above. If you wish to allow use of your version of this file only
  751.  * under the terms of either the GPL or the LGPL, and not to allow others to
  752.  * use your version of this file under the terms of the MPL, indicate your
  753.  * decision by deleting the provisions above and replace them with the notice
  754.  * and other provisions required by the GPL or the LGPL. If you do not delete
  755.  * the provisions above, a recipient may use your version of this file under
  756.  * the terms of any one of the MPL, the GPL or the LGPL.
  757.  *
  758.  * ***** END LICENSE BLOCK ***** */
  759.  
  760. Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
  761. Components.utils.import("resource://gre/modules/AddonManager.jsm");
  762.  
  763. //=================================================
  764. // Shutdown - used to store cleanup functions which will
  765. //            be called on Application shutdown
  766. var gShutdown = [];
  767.  
  768. //=================================================
  769. // Console constructor
  770. function Console() {
  771.   this._console = Components.classes["@mozilla.org/consoleservice;1"]
  772.     .getService(Ci.nsIConsoleService);
  773. }
  774.  
  775. //=================================================
  776. // Console implementation
  777. Console.prototype = {
  778.   log : function cs_log(aMsg) {
  779.     this._console.logStringMessage(aMsg);
  780.   },
  781.  
  782.   open : function cs_open() {
  783.     var wMediator = Components.classes["@mozilla.org/appshell/window-mediator;1"]
  784.                               .getService(Ci.nsIWindowMediator);
  785.     var console = wMediator.getMostRecentWindow("global:console");
  786.     if (!console) {
  787.       var wWatch = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
  788.                              .getService(Ci.nsIWindowWatcher);
  789.       wWatch.openWindow(null, "chrome://global/content/console.xul", "_blank",
  790.                         "chrome,dialog=no,all", null);
  791.     } else {
  792.       // console was already open
  793.       console.focus();
  794.     }
  795.   },
  796.  
  797.   QueryInterface : XPCOMUtils.generateQI([Ci.extIConsole])
  798. };
  799.  
  800.  
  801. //=================================================
  802. // EventItem constructor
  803. function EventItem(aType, aData) {
  804.   this._type = aType;
  805.   this._data = aData;
  806. }
  807.  
  808. //=================================================
  809. // EventItem implementation
  810. EventItem.prototype = {
  811.   _cancel : false,
  812.  
  813.   get type() {
  814.     return this._type;
  815.   },
  816.  
  817.   get data() {
  818.     return this._data;
  819.   },
  820.  
  821.   preventDefault : function ei_pd() {
  822.     this._cancel = true;
  823.   },
  824.  
  825.   QueryInterface : XPCOMUtils.generateQI([Ci.extIEventItem])
  826. };
  827.  
  828.  
  829. //=================================================
  830. // Events constructor
  831. function Events(notifier) {
  832.   this._listeners = [];
  833.   this._notifier = notifier;
  834. }
  835.  
  836. //=================================================
  837. // Events implementation
  838. Events.prototype = {
  839.   addListener : function evts_al(aEvent, aListener) {
  840.     function hasFilter(element) {
  841.       return element.event == aEvent && element.listener == aListener;
  842.     }
  843.  
  844.     if (this._listeners.some(hasFilter))
  845.       return;
  846.  
  847.     this._listeners.push({
  848.       event: aEvent,
  849.       listener: aListener
  850.     });
  851.  
  852.     if (this._notifier) {
  853.       this._notifier(aEvent, aListener);
  854.     }
  855.   },
  856.  
  857.   removeListener : function evts_rl(aEvent, aListener) {
  858.     function hasFilter(element) {
  859.       return (element.event != aEvent) || (element.listener != aListener);
  860.     }
  861.  
  862.     this._listeners = this._listeners.filter(hasFilter);
  863.   },
  864.  
  865.   dispatch : function evts_dispatch(aEvent, aEventItem) {
  866.     var eventItem = new EventItem(aEvent, aEventItem);
  867.  
  868.     this._listeners.forEach(function(key){
  869.       if (key.event == aEvent) {
  870.         key.listener.handleEvent ?
  871.           key.listener.handleEvent(eventItem) :
  872.           key.listener(eventItem);
  873.       }
  874.     });
  875.  
  876.     return !eventItem._cancel;
  877.   },
  878.  
  879.   QueryInterface : XPCOMUtils.generateQI([Ci.extIEvents])
  880. };
  881.  
  882.  
  883. //=================================================
  884. // PreferenceBranch constructor
  885. function PreferenceBranch(aBranch) {
  886.   if (!aBranch)
  887.     aBranch = "";
  888.  
  889.   this._root = aBranch;
  890.   this._prefs = Components.classes["@mozilla.org/preferences-service;1"]
  891.                           .getService(Ci.nsIPrefService);
  892.  
  893.   if (aBranch)
  894.     this._prefs = this._prefs.getBranch(aBranch);
  895.  
  896.   this._prefs.QueryInterface(Ci.nsIPrefBranch);
  897.   this._prefs.QueryInterface(Ci.nsIPrefBranch2);
  898.  
  899.   // we want to listen to "all" changes for this branch, so pass in a blank domain
  900.   this._prefs.addObserver("", this, true);
  901.   this._events = new Events();
  902.  
  903.   var self = this;
  904.   gShutdown.push(function() { self._shutdown(); });
  905. }
  906.  
  907. //=================================================
  908. // PreferenceBranch implementation
  909. PreferenceBranch.prototype = {
  910.   // cleanup observer so we don't leak
  911.   _shutdown: function prefs_shutdown() {
  912.     this._prefs.removeObserver(this._root, this);
  913.  
  914.     this._prefs = null;
  915.     this._events = null;
  916.   },
  917.  
  918.   // for nsIObserver
  919.   observe: function prefs_observe(aSubject, aTopic, aData) {
  920.     if (aTopic == "nsPref:changed")
  921.       this._events.dispatch("change", aData);
  922.   },
  923.  
  924.   get root() {
  925.     return this._root;
  926.   },
  927.  
  928.   get all() {
  929.     return this.find({});
  930.   },
  931.  
  932.   get events() {
  933.     return this._events;
  934.   },
  935.  
  936.   // XXX: Disabled until we can figure out the wrapped object issues
  937.   // name: "name" or /name/
  938.   // path: "foo.bar." or "" or /fo+\.bar/
  939.   // type: Boolean, Number, String (getPrefType)
  940.   // locked: true, false (prefIsLocked)
  941.   // modified: true, false (prefHasUserValue)
  942.   find : function prefs_find(aOptions) {
  943.     var retVal = [];
  944.     var items = this._prefs.getChildList("");
  945.  
  946.     for (var i = 0; i < items.length; i++) {
  947.       retVal.push(new Preference(items[i], this));
  948.     }
  949.  
  950.     return retVal;
  951.   },
  952.  
  953.   has : function prefs_has(aName) {
  954.     return (this._prefs.getPrefType(aName) != Ci.nsIPrefBranch.PREF_INVALID);
  955.   },
  956.  
  957.   get : function prefs_get(aName) {
  958.     return this.has(aName) ? new Preference(aName, this) : null;
  959.   },
  960.  
  961.   getValue : function prefs_gv(aName, aValue) {
  962.     var type = this._prefs.getPrefType(aName);
  963.  
  964.     switch (type) {
  965.       case Ci.nsIPrefBranch2.PREF_STRING:
  966.         aValue = this._prefs.getComplexValue(aName, Ci.nsISupportsString).data;
  967.         break;
  968.       case Ci.nsIPrefBranch2.PREF_BOOL:
  969.         aValue = this._prefs.getBoolPref(aName);
  970.         break;
  971.       case Ci.nsIPrefBranch2.PREF_INT:
  972.         aValue = this._prefs.getIntPref(aName);
  973.         break;
  974.     }
  975.  
  976.     return aValue;
  977.   },
  978.  
  979.   setValue : function prefs_sv(aName, aValue) {
  980.     var type = aValue != null ? aValue.constructor.name : "";
  981.  
  982.     switch (type) {
  983.       case "String":
  984.         var str = Components.classes["@mozilla.org/supports-string;1"]
  985.                             .createInstance(Ci.nsISupportsString);
  986.         str.data = aValue;
  987.         this._prefs.setComplexValue(aName, Ci.nsISupportsString, str);
  988.         break;
  989.       case "Boolean":
  990.         this._prefs.setBoolPref(aName, aValue);
  991.         break;
  992.       case "Number":
  993.         this._prefs.setIntPref(aName, aValue);
  994.         break;
  995.       default:
  996.         throw("Unknown preference value specified.");
  997.     }
  998.   },
  999.  
  1000.   reset : function prefs_reset() {
  1001.     this._prefs.resetBranch("");
  1002.   },
  1003.  
  1004.   QueryInterface : XPCOMUtils.generateQI([Ci.extIPreferenceBranch, Ci.nsISupportsWeakReference])
  1005. };
  1006.  
  1007.  
  1008. //=================================================
  1009. // Preference constructor
  1010. function Preference(aName, aBranch) {
  1011.   this._name = aName;
  1012.   this._branch = aBranch;
  1013.   this._events = new Events();
  1014.  
  1015.   var self = this;
  1016.  
  1017.   this.branch.events.addListener("change", function(aEvent){
  1018.     if (aEvent.data == self.name)
  1019.       self.events.dispatch(aEvent.type, aEvent.data);
  1020.   });
  1021. }
  1022.  
  1023. //=================================================
  1024. // Preference implementation
  1025. Preference.prototype = {
  1026.   get name() {
  1027.     return this._name;
  1028.   },
  1029.  
  1030.   get type() {
  1031.     var value = "";
  1032.     var type = this.branch._prefs.getPrefType(this._name);
  1033.  
  1034.     switch (type) {
  1035.       case Ci.nsIPrefBranch2.PREF_STRING:
  1036.         value = "String";
  1037.         break;
  1038.       case Ci.nsIPrefBranch2.PREF_BOOL:
  1039.         value = "Boolean";
  1040.         break;
  1041.       case Ci.nsIPrefBranch2.PREF_INT:
  1042.         value = "Number";
  1043.         break;
  1044.     }
  1045.  
  1046.     return value;
  1047.   },
  1048.  
  1049.   get value() {
  1050.     return this.branch.getValue(this._name, null);
  1051.   },
  1052.  
  1053.   set value(aValue) {
  1054.     return this.branch.setValue(this._name, aValue);
  1055.   },
  1056.  
  1057.   get locked() {
  1058.     return this.branch._prefs.prefIsLocked(this.name);
  1059.   },
  1060.  
  1061.   set locked(aValue) {
  1062.     this.branch._prefs[ aValue ? "lockPref" : "unlockPref" ](this.name);
  1063.   },
  1064.  
  1065.   get modified() {
  1066.     return this.branch._prefs.prefHasUserValue(this.name);
  1067.   },
  1068.  
  1069.   get branch() {
  1070.     return this._branch;
  1071.   },
  1072.  
  1073.   get events() {
  1074.     return this._events;
  1075.   },
  1076.  
  1077.   reset : function pref_reset() {
  1078.     this.branch._prefs.clearUserPref(this.name);
  1079.   },
  1080.  
  1081.   QueryInterface : XPCOMUtils.generateQI([Ci.extIPreference])
  1082. };
  1083.  
  1084.  
  1085. //=================================================
  1086. // SessionStorage constructor
  1087. function SessionStorage() {
  1088.   this._storage = {};
  1089.   this._events = new Events();
  1090. }
  1091.  
  1092. //=================================================
  1093. // SessionStorage implementation
  1094. SessionStorage.prototype = {
  1095.   get events() {
  1096.     return this._events;
  1097.   },
  1098.  
  1099.   has : function ss_has(aName) {
  1100.     return this._storage.hasOwnProperty(aName);
  1101.   },
  1102.  
  1103.   set : function ss_set(aName, aValue) {
  1104.     this._storage[aName] = aValue;
  1105.     this._events.dispatch("change", aName);
  1106.   },
  1107.  
  1108.   get : function ss_get(aName, aDefaultValue) {
  1109.     return this.has(aName) ? this._storage[aName] : aDefaultValue;
  1110.   },
  1111.  
  1112.   QueryInterface : XPCOMUtils.generateQI([Ci.extISessionStorage])
  1113. };
  1114.  
  1115.  
  1116. //=================================================
  1117. // Extension constructor
  1118. function Extension(aItem) {
  1119.   this._item = aItem;
  1120.   this._firstRun = false;
  1121.   this._prefs = new PreferenceBranch("extensions." + this.id + ".");
  1122.   this._storage = new SessionStorage();
  1123.   this._events = new Events();
  1124.  
  1125.   var installPref = "install-event-fired";
  1126.   if (!this._prefs.has(installPref)) {
  1127.     this._prefs.setValue(installPref, true);
  1128.     this._firstRun = true;
  1129.   }
  1130.  
  1131.   AddonManager.addAddonListener(this);
  1132.   AddonManager.addInstallListener(this);
  1133.  
  1134.   var self = this;
  1135.   gShutdown.push(function(){ self._shutdown(); });
  1136. }
  1137.  
  1138. //=================================================
  1139. // Extension implementation
  1140. Extension.prototype = {
  1141.   // cleanup observer so we don't leak
  1142.   _shutdown: function ext_shutdown() {
  1143.     AddonManager.removeAddonListener(this);
  1144.     AddonManager.removeInstallListener(this);
  1145.  
  1146.     this._prefs = null;
  1147.     this._storage = null;
  1148.     this._events = null;
  1149.   },
  1150.  
  1151.   // for AddonListener
  1152.   onDisabling: function(addon, needsRestart) {
  1153.     if (addon.id == this.id)
  1154.       this._events.dispatch("disable", this.id);
  1155.   },
  1156.  
  1157.   onEnabling: function(addon, needsRestart) {
  1158.     if (addon.id == this.id)
  1159.       this._events.dispatch("enable", this.id);
  1160.   },
  1161.  
  1162.   onUninstalling: function(addon, needsRestart) {
  1163.     if (addon.id == this.id)
  1164.       this._events.dispatch("uninstall", this.id);
  1165.   },
  1166.  
  1167.   onOperationCancelled: function(addon) {
  1168.     if (addon.id == this.id)
  1169.       this._events.dispatch("cancel", this.id);
  1170.   },
  1171.  
  1172.   onInstallEnded: function(install, addon) {
  1173.     if (addon.id == this.id)
  1174.       this._events.dispatch("upgrade", this.id);
  1175.   },
  1176.  
  1177.   get id() {
  1178.     return this._item.id;
  1179.   },
  1180.  
  1181.   get name() {
  1182.     return this._item.name;
  1183.   },
  1184.  
  1185.   get enabled() {
  1186.     return this._item.isActive;
  1187.   },
  1188.  
  1189.   get version() {
  1190.     return this._item.version;
  1191.   },
  1192.  
  1193.   get firstRun() {
  1194.     return this._firstRun;
  1195.   },
  1196.  
  1197.   get storage() {
  1198.     return this._storage;
  1199.   },
  1200.  
  1201.   get prefs() {
  1202.     return this._prefs;
  1203.   },
  1204.  
  1205.   get events() {
  1206.     return this._events;
  1207.   },
  1208.  
  1209.   QueryInterface : XPCOMUtils.generateQI([Ci.extIExtension])
  1210. };
  1211.  
  1212.  
  1213. //=================================================
  1214. // Extensions constructor
  1215. function Extensions(addons) {
  1216.   this._cache = {};
  1217.  
  1218.   addons.forEach(function(addon) {
  1219.     this._cache[addon.id] = new Extension(addon);
  1220.   }, this);
  1221.  
  1222.   var self = this;
  1223.   gShutdown.push(function() { self._shutdown(); });
  1224. }
  1225.  
  1226. //=================================================
  1227. // Extensions implementation
  1228. Extensions.prototype = {
  1229.   _shutdown : function exts_shutdown() {
  1230.     this._cache = null;
  1231.   },
  1232.  
  1233.   get all() {
  1234.     return this.find({});
  1235.   },
  1236.  
  1237.   // XXX: Disabled until we can figure out the wrapped object issues
  1238.   // id: "some@id" or /id/
  1239.   // name: "name" or /name/
  1240.   // version: "1.0.1"
  1241.   // minVersion: "1.0"
  1242.   // maxVersion: "2.0"
  1243.   find : function exts_find(aOptions) {
  1244.     return [e for each (e in this._cache)];
  1245.   },
  1246.  
  1247.   has : function exts_has(aId) {
  1248.     return aId in this._cache;
  1249.   },
  1250.  
  1251.   get : function exts_get(aId) {
  1252.     return this.has(aId) ? this._cache[aId] : null;
  1253.   },
  1254.  
  1255.   QueryInterface : XPCOMUtils.generateQI([Ci.extIExtensions])
  1256. };
  1257.  
  1258. //=================================================
  1259. // extApplication constructor
  1260. function extApplication() {
  1261. }
  1262.  
  1263. //=================================================
  1264. // extApplication implementation
  1265. extApplication.prototype = {
  1266.   initToolkitHelpers: function extApp_initToolkitHelpers() {
  1267.     XPCOMUtils.defineLazyServiceGetter(this, "_info",
  1268.                                        "@mozilla.org/xre/app-info;1",
  1269.                                        "nsIXULAppInfo");
  1270.  
  1271.     // While the other event listeners are loaded only if needed,
  1272.     // FUEL *must* listen for shutdown in order to clean up it's
  1273.     // references to various services, and to remove itself as
  1274.     // observer of any other notifications.
  1275.     this._obs = Cc["@mozilla.org/observer-service;1"].
  1276.                 getService(Ci.nsIObserverService);
  1277.     this._obs.addObserver(this, "xpcom-shutdown", false);
  1278.     this._registered = {"unload": true};
  1279.   },
  1280.  
  1281.   classInfo: XPCOMUtils.generateCI({interfaces: [Ci.extIApplication,
  1282.                                                  Ci.nsIObserver],
  1283.                                     flags: Ci.nsIClassInfo.SINGLETON}),
  1284.  
  1285.   // extIApplication
  1286.   get id() {
  1287.     return this._info.ID;
  1288.   },
  1289.  
  1290.   get name() {
  1291.     return this._info.name;
  1292.   },
  1293.  
  1294.   get version() {
  1295.     return this._info.version;
  1296.   },
  1297.  
  1298.   // for nsIObserver
  1299.   observe: function app_observe(aSubject, aTopic, aData) {
  1300.     if (aTopic == "app-startup") {
  1301.       this.events.dispatch("load", "application");
  1302.     }
  1303.     else if (aTopic == "final-ui-startup") {
  1304.       this.events.dispatch("ready", "application");
  1305.     }
  1306.     else if (aTopic == "quit-application-requested") {
  1307.       // we can stop the quit by checking the return value
  1308.       if (this.events.dispatch("quit", "application") == false)
  1309.         aSubject.data = true;
  1310.     }
  1311.     else if (aTopic == "xpcom-shutdown") {
  1312.  
  1313.       this.events.dispatch("unload", "application");
  1314.  
  1315.       // call the cleanup functions and empty the array
  1316.       while (gShutdown.length) {
  1317.         gShutdown.shift()();
  1318.       }
  1319.  
  1320.       // release our observers
  1321.       this._obs.removeObserver(this, "app-startup");
  1322.       this._obs.removeObserver(this, "final-ui-startup");
  1323.       this._obs.removeObserver(this, "quit-application-requested");
  1324.       this._obs.removeObserver(this, "xpcom-shutdown");
  1325.     }
  1326.   },
  1327.  
  1328.   get console() {
  1329.     let console = new Console();
  1330.     this.__defineGetter__("console", function() console);
  1331.     return this.console;
  1332.   },
  1333.  
  1334.   get storage() {
  1335.     let storage = new SessionStorage();
  1336.     this.__defineGetter__("storage", function() storage);
  1337.     return this.storage;
  1338.   },
  1339.  
  1340.   get prefs() {
  1341.     let prefs = new PreferenceBranch("");
  1342.     this.__defineGetter__("prefs", function() prefs);
  1343.     return this.prefs;
  1344.   },
  1345.  
  1346.   getExtensions: function(callback) {
  1347.     AddonManager.getAddonsByTypes(["extension"], function(addons) {
  1348.       callback.callback(new Extensions(addons));
  1349.     });
  1350.   },
  1351.  
  1352.   get events() {
  1353.  
  1354.     // This ensures that FUEL only registers for notifications as needed
  1355.     // by callers. Note that the unload (xpcom-shutdown) event is listened
  1356.     // for by default, as it's needed for cleanup purposes.
  1357.     var self = this;
  1358.     function registerCheck(aEvent) {
  1359.       var rmap = { "load": "app-startup",
  1360.                    "ready": "final-ui-startup",
  1361.                    "quit": "quit-application-requested"};
  1362.       if (!(aEvent in rmap) || aEvent in self._registered)
  1363.         return;
  1364.  
  1365.       self._obs.addObserver(self, rmap[aEvent]);
  1366.       self._registered[aEvent] = true;
  1367.     }
  1368.  
  1369.     let events = new Events(registerCheck);
  1370.     this.__defineGetter__("events", function() events);
  1371.     return this.events;
  1372.   },
  1373.  
  1374.   // helper method for correct quitting/restarting
  1375.   _quitWithFlags: function app__quitWithFlags(aFlags) {
  1376.     let cancelQuit = Components.classes["@mozilla.org/supports-PRBool;1"]
  1377.                                .createInstance(Components.interfaces.nsISupportsPRBool);
  1378.     let quitType = aFlags & Components.interfaces.nsIAppStartup.eRestart ? "restart" : null;
  1379.     this._obs.notifyObservers(cancelQuit, "quit-application-requested", quitType);
  1380.     if (cancelQuit.data)
  1381.       return false; // somebody canceled our quit request
  1382.  
  1383.     let appStartup = Components.classes['@mozilla.org/toolkit/app-startup;1']
  1384.                                .getService(Components.interfaces.nsIAppStartup);
  1385.     appStartup.quit(aFlags);
  1386.     return true;
  1387.   },
  1388.  
  1389.   quit: function app_quit() {
  1390.     return this._quitWithFlags(Components.interfaces.nsIAppStartup.eAttemptQuit);
  1391.   },
  1392.  
  1393.   restart: function app_restart() {
  1394.     return this._quitWithFlags(Components.interfaces.nsIAppStartup.eAttemptQuit |
  1395.                                Components.interfaces.nsIAppStartup.eRestart);
  1396.   },
  1397.  
  1398.   QueryInterface : XPCOMUtils.generateQI([Ci.extIApplication, Ci.nsISupportsWeakReference])
  1399. };
  1400. //@line 724 "/tmp/buildd/iceweasel-10.0.12esr/browser/fuel/src/fuelApplication.js"
  1401.  
  1402. // set the proto, defined in extApplication.js
  1403. Application.prototype.__proto__ = extApplication.prototype;
  1404.  
  1405. var NSGetFactory = XPCOMUtils.generateNSGetFactory([Application]);
  1406.  
  1407.